<template>
  <view
    class="tn-switch"
    :class="[switchClass]"
    :style="switchStyle"
    @tap.stop="handleSwitchClick"
  >
    <!-- 滑块 -->
    <view class="tn-switch__bar" :style="switchBarStyle">
      <!-- 加载状态 -->
      <tn-loading :show="loading" mode="flower"></tn-loading>
    </view>
    <!-- 激活时的图标 -->
    <view
      v-if="activeIcon"
      class="tn-switch__icon tn-switch__icon--active"
    >
      <tn-icon :icon="activeIcon"></tn-icon>
    </view>
    <!-- 未激活时的图标 -->
    <view
      v-if="inactiveIcon"
      class="tn-switch__icon tn-switch__icon--inactive"
    >
      <tn-icon :icon="inactiveIcon"></tn-icon>
    </view>
  </view>
</template>

<script lang="ts" setup>
import { switchProps, switchEmits } from '../../../types/tn-switch'
import { ColorInfo } from '../../../types/tuniao-ui'
import useComponentColor from '../../../libs/hooks/useComponentColor'
import { ref, computed, CSSProperties, watch } from 'vue'
import { TuniaoSizes, TuniaoSize } from '../../../types/tuniao-ui'
import { handleValueWithUnit } from '../../../utils'
import TnLoading from '../../tn-loading/src/Loading.vue'
import TnIcon from '../../tn-icon/src/Icon.vue'
import { UPDATE_MODEL_EVENT } from '../../../constants'


const props = defineProps(switchProps)
const emits = defineEmits(switchEmits)

// 解析颜色
const { splitColorInfo } = useComponentColor()
// 解析激活时颜色
const activeColor = computed<ColorInfo>(() => {
  return splitColorInfo('bg', props?.activeColor || '')
})
// 解析未激活时颜色
const inactiveColor = computed<ColorInfo>(() => {
  return splitColorInfo('bg', props?.inactiveColor || '')
})

// switch样式
const switchStyle = computed<CSSProperties>(() => {
  let style: CSSProperties = {}
  if (props?.size && !TuniaoSizes.includes(props.size as TuniaoSize)) {
    style.fontSize = handleValueWithUnit(props.size)
  }
  if (switchState.value) {
    if (activeColor.value.type === 'style') style.backgroundColor = activeColor.value.value
  } else {
    if (inactiveColor.value.type === 'style') style.backgroundColor = inactiveColor.value.value
  }
  return style
})
// switch滑块样式
const switchBarStyle = computed<CSSProperties>(() => {
  let style: CSSProperties = {}
  if (props?.size && !TuniaoSizes.includes(props.size as TuniaoSize)) {
    style.width = handleValueWithUnit(props.size)
    style.height = style.width
  }
  return style
})

// switch对应的类
const switchClass = computed<string>(() => {
  let clazz: string[] = []
  if (props.disabled) clazz.push('disabled')
  if (props?.size && TuniaoSizes.includes(props.size as TuniaoSize)) {
    clazz.push(`tn-switch--${props.size}`)
  }
  if (props?.shape) {
    clazz.push(`tn-switch--${props.shape}`)
  }
  if (switchState.value) {
    clazz.push('active')
    if (activeColor.value.type === 'class') clazz.push(activeColor.value.value)
  } else {
    if (inactiveColor.value.type === 'class') clazz.push(inactiveColor.value.value)
  }
  return clazz.join(' ')
})

// switch状态
let switchState = ref<boolean>(false)
watch(() => props.modelValue, (val) => {
  if (val === props.activeValue) {
    switchState.value = true
  } else {
    switchState.value = false
  }
}, {
  immediate: true
})

// 处理switch点击事件
const handleSwitchClick = () => {
  if (props.loading || props.disabled) return
  emits('change', switchState.value ? props.inactiveValue : props.activeValue)
  emits(UPDATE_MODEL_EVENT, switchState.value ? props.inactiveValue : props.activeValue)
}
</script>

<script lang="ts">
export default {
  options: {
    // 在微信小程序中将组件节点渲染为虚拟节点，更加接近Vue组件的表现(不会出现shadow节点下再去创建元素)
    virtualHost: true
  }
}
</script>

<style lang="scss" scoped>

@import '../../../theme.scss';
.tn-switch {
  position: relative;
  display: inline-block;
  box-sizing: content-box;
  width: 2em;
  height: 1em;
  font-size: 50rpx;
  background-color: #AAAAAA;
  transition: background-color 0.25s;

  &__bar {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 0;
    left: 0;
    background-color: #FFFFFF;
    width: 50rpx;
    height: 50rpx;
    transform-origin: center center;
    transform: scale(0.9);
    box-shadow: 0 6rpx 2rpx 0 rgba(0, 0, 0, 0.05), 0 4rpx 4rpx 0 rgba(0, 0, 0, 0.1), 0 6rpx 6rpx 0 rgba(0, 0, 0, 0.05);
    transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
    -webkit-transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);

    .tn-loading {
      width: 90%;
      height: 90%;
    }
  }

  &__icon {
    font-size: inherit;
    line-height: 1;
    color: #FFFFFF;
    position: absolute;
    transform-origin: 50% 50%;
    transition: transform 0.3s ease-in-out;
    top: 0;

    &--active {
      left: 0;
      transform: scale(0);
    }
    &--inactive {
      right: 0;
      transform: scale(0.8);
    }
  }

  &.disabled {
    opacity: 0.4;
  }
  /* 激活与非激活状态 start */
  &.active {
    background-color: $tn-main-color;
    .tn-switch__icon--active {
      transform: scale(0.8);
    }
    .tn-switch__icon--inactive {
      transform: scale(0);
    }
    .tn-switch__bar {
      transform: translateX(100%) scale(0.9);
    }
  }
  /* 激活与非激活状态 end */

  /* 内置形状 start */
  &--square {
    border-radius: 6rpx;
    .tn-switch__bar {
      border-radius: 6rpx;
    }
  }
  &--round {
    border-radius: 1000rpx;
    .tn-switch__bar {
      border-radius: 50%;
    }
  }
  /* 内置形状 end */

  /* 内置大小 start */
  &--sm {
    font-size: 40rpx;
    .tn-switch__bar {
      width: 40rpx;
      height: 40rpx;
    }
  }
  &--lg {
    font-size: 60rpx;
    .tn-switch__bar {
      width: 60rpx;
      height: 60rpx;
    }
  }
  &--xl {
    font-size: 70rpx;
    .tn-switch__bar {
      width: 70rpx;
      height: 70rpx;
    }
  }
  /* 内置大小 end */
}
</style>
